//
//  ATVMidiController.m
//  FlashController
//
//  Created by Martin Schiøth Dyrby on 11/15/11.
//  Copyright 2011 Molamil. All rights reserved.
//

#import "ATVMidiController.h"
#include "RtMidi.h"

@implementation ATVMidiController

@synthesize nextControlListeners;
@synthesize controlListeners;
@synthesize stepControlListeners;
@synthesize decrementValue;
@synthesize incrementValue;

RtMidiIn *midiin = 0;

- (id)init
{
    
    self = [super init];
    if (self) {
        
        // Initialization code here.
        
        [self setup];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(waitHandler:) name:@"waitForMidi" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(assignHandler:) name:@"assignMidi" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(loadNewURLHandler:) name:@"loadNewURL" object: nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(removePathHandler:) name:@"deassignMidi" object: nil];
    }
    
    return self;
}



- (void) setup{
    
	nextControlListeners =	[[NSMutableArray alloc] init];
	controlListeners =		[[NSMutableArray alloc] init];
	stepControlListeners =	[[NSMutableArray alloc] init];
	
	decrementValue = [NSNumber numberWithInt: 40];
	incrementValue = [NSNumber numberWithInt: 87];
	
	try {
		midiin = new RtMidiIn();
        
		midiin->openPort( 0 );
        
		midiin->ignoreTypes( false, false, false );
        
		unsigned int nPorts = midiin->getPortCount();
        
		std::string portName;
		for ( unsigned int i=0; i<nPorts; i++ ) {
			try {
				portName = midiin->getPortName(i);
			}
			catch ( RtError &error ) {
				error.printMessage();
			}
		}
	}
	catch (RtError &error) {
		error.printMessage();
	}
    
	if(midiin) {
        NSLog(@"midiin");
		[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkMidiIn:) userInfo:nil repeats:YES];
	}
}

- (void) loadNewURLHandler: (NSNotification*) note {
    [nextControlListeners release];
    [controlListeners release];
	nextControlListeners =	[[NSMutableArray alloc] init];
	controlListeners =		[[NSMutableArray alloc] init];
}

- (void) removePathHandler: (NSNotification*) note {
    
    NSDictionary* dict = (NSDictionary*) note.object;
    
	NSDictionary* listener;	
	NSUInteger i;
    for(i = 0; i < [controlListeners count]; i++) {
        listener = [controlListeners objectAtIndex:i];
        
        id listenerID = [listener valueForKey:@"receiver"];
        id dictionaryID = [dict valueForKey:@"receiver"];

        if([listenerID isEqual: dictionaryID]){
            [controlListeners removeObjectAtIndex:i];
            break;
        }
    }
}

- (void)checkMidiIn:(NSTimer *) timer {
    
	std::vector<unsigned char> message;
	midiin->getMessage( &message );
	NSArray* listener;	
	NSUInteger i;
	id receiver;
	NSString* aSelectorName;
	NSNumber* controlType;
	NSNumber* controlNum;
    NSDictionary* dict;
	
	int nBytes;
	
	nBytes = floor(message.size());
    
	if ( nBytes > 0) {
		NSNumber* type = [NSNumber numberWithInt: message[0]];
		NSNumber* num = [NSNumber numberWithInt: message[1]];
		NSNumber* value = [NSNumber numberWithInt: message[2]];
        
		// check value listeners
		for(i = 0; i < [controlListeners count]; i++) {
            dict = [controlListeners objectAtIndex:i];

			controlType = [dict valueForKey:@"controlType"];
			controlNum = [dict valueForKey:@"controlNum"];
			aSelectorName = [dict valueForKey:@"selector"];
			receiver = [dict valueForKey:@"receiver"];	
            
			if([controlType intValue] == [type intValue] && [controlNum intValue]== [num intValue]){
				[receiver performSelector:NSSelectorFromString(aSelectorName) withObject: value];
			}
		}

		// Check next control listeners
		for (i = 0; i < [nextControlListeners count]; i++) {
			listener = [nextControlListeners objectAtIndex:i];
			
			aSelectorName = [listener objectAtIndex:0];
			receiver = [listener objectAtIndex:1];
			
			[receiver performSelector:NSSelectorFromString(aSelectorName) withObject: type withObject: num];
		}
		[nextControlListeners removeAllObjects];
	}
}














- (void) waitHandler: (NSNotification*) note {
    NSDictionary* dict = (NSDictionary*)note.object;
    NSString* selectorName = [dict valueForKey:@"selector"];
    id receiver = [dict valueForKey:@"receiver"];
	NSDictionary* listener;	
	NSUInteger i;
    for(i = 0; i < [controlListeners count]; i++) {
        listener = [controlListeners objectAtIndex:i];
        
        if([listener valueForKey:@"receiver"] == receiver){
            [controlListeners removeObjectAtIndex:i];
            break;
        }
    }
    
    [self addListenerForNextControl:selectorName forObject:receiver];
}

- (void) addListenerForNextControl: (NSString*) selectorName forObject: (id) receiver{
	BOOL insert = YES;
	for (NSUInteger i = 0; i < [nextControlListeners count]; i++) {
		NSArray* listener = [nextControlListeners objectAtIndex:i];
		NSString* regSelectorName = [listener objectAtIndex:1];
		id regObject = [listener objectAtIndex:2];
		
		if([regSelectorName isEqualToString:selectorName] && regObject==receiver) {
			insert = NO;
			break;
		}
	}
	
	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		
		[nextControlListeners addObject:insertArray];
	}
}











- (void) assignHandler: (NSNotification*) note {
    NSDictionary* dict = (NSDictionary*)note.object;
/*    NSNumber* controlType = [dict valueForKey:@"controlType"];
    NSNumber* controlNum = [dict valueForKey:@"controlNum"];
    NSString* selectorName = [dict valueForKey:@"selector"];
    id receiver = [dict valueForKey:@"receiver"];
    NSString* path = [dict valueForKey:@"path"];*/
    
    [self addListenerWithDict: dict];
//    [self addListenerForControl:controlType withNum: controlNum forSelectorName: selectorName forObject:receiver];
}
- (void) addListenerForControl: (NSNumber*) controlType withNum: (NSNumber*) controlNum forSelectorName: (NSString*) selectorName forObject: (id) receiver{
	BOOL insert = YES;

	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: controlType];
		[insertArray addObject: controlNum];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		[controlListeners addObject:insertArray];
	}
}


- (void) addListenerWithDict: (NSDictionary*) dict{
		[controlListeners addObject:dict];
/*	BOOL insert = YES;
    
	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: controlType];
		[insertArray addObject: controlNum];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		[controlListeners addObject:insertArray];
	}*/
}

@end